package com.xianjindai.facade.utils;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.ParseException;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.ByteArrayBody;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import com.xianjindai.commons.constant.CommonConstants;
import com.xianjindai.commons.dto.ResultDto;
import com.xianjindai.commons.member.model.Member;
import com.xianjindai.commons.utils.IdCardUtils;
import com.xianjindai.facade.borrow.constant.BorrowImgConstants;
import com.xianjindai.facade.file.constant.FileContants;

import net.sf.json.JSONObject;

/**
 * face++接口封装Utils
 * @author D
 *
 */
public class FaceIdUtils {
	//身份证正面
	private static final String IDCARD_FRONT = "front";
	//身份证反面
	private static final String IDCARD_BACK = "back";
	//合法度校验比例
	private static final double LEGALITY_PROPORTION = 0.8d;
	private static final int CODE_200 = 200;
	private static final int CODE_400 = 400;
	private static final int CODE_403 = 403;
	private static final int CODE_413 = 413;
	private static final int CODE_404 = 404;
	private static final int CODE_500 = 500;
	private static final Logger LOGGER = LogManager.getLogger(FaceIdUtils.class.getName()); 
	private FaceIdUtils(){}
	
	/**
	 * 校验身份证照片的合法性
	 * @param member
	 * @param fileContants
	 * @param cardFile
	 * @param cardType
	 * @return
	 */
	public static ResultDto ocridcard(Member member, FileContants fileContants,
			byte[] cardFile, String cardType){
		
		cardType = BorrowImgConstants.IMG_TYPE_1.equals(cardType) ? IDCARD_FRONT : IDCARD_BACK;
		
		ResultDto result = new ResultDto();
		result.setCode(CommonConstants.REQ_RESULT_FAIL);
		//创建HttpClient对象
		CloseableHttpClient closeHttpClient = HttpClients.createDefault();
		CloseableHttpResponse httpResponse = null;
		//发送Post请求
		HttpPost httpPost = new HttpPost(fileContants.getFaceApiOcridcardUrl());

		//设置Post参数
		MultipartEntity reqEntity = new MultipartEntity();

		try {
			reqEntity.addPart("api_key", new StringBody(fileContants.getFaceApiKey()));
			reqEntity.addPart("api_secret", new StringBody(fileContants.getFaceApiSecret()));
			//返回身份证照片合法性检查结果，值只取“0”或“1”。“1”：返回； “0”：不返回。默认“0”
			reqEntity.addPart("legality",new StringBody("1"));
		} catch (UnsupportedEncodingException e1) {
			LOGGER.error("************************身份证证件识别参数错误*******************************");
			e1.printStackTrace();
		}
		
		reqEntity.addPart("image", new ByteArrayBody(cardFile, ""));
		//转换参数并设置编码格式
		httpPost.setEntity(reqEntity);
		//执行Post请求 得到Response对象
		try {
			httpResponse = closeHttpClient.execute(httpPost);
		} catch (ClientProtocolException e) {
			LOGGER.error("身份证证件识别请求错误" + e.getMessage(), e);
		} catch (IOException e) {
			LOGGER.error("身份证证件识别请求错误" + e.getMessage(), e);
		}finally {
			closeIO(httpResponse, closeHttpClient);
		}
		
		result = checkHttpCode(httpResponse);
		
		if(CommonConstants.REQ_RESULT_FAIL.equals(result.getCode())){
			return result;
		}
		
		//把返回结果封装成json对象
        JSONObject jsonResult = null;
        if(httpResponse.getEntity() != null){
        	try {
				jsonResult = JSONObject.fromObject(EntityUtils.toString(httpResponse.getEntity(), "UTF-8"));
			} catch (ParseException e) {
				LOGGER.error("身份证证件识别返回值解析" + e.getMessage(), e);
			} catch (IOException e) {
				LOGGER.error("身份证证件识别返回值解析" + e.getMessage(), e);
			}
        }
        
        if(httpResponse.getEntity() == null || jsonResult == null){
        	result.setCode(CommonConstants.REQ_RESULT_FAIL);
        	result.setMessage("请求失败，请重试");
        	
        	return result;
        }
        //获取图片识别的正反面是否与传入的一致
		if(!StringUtils.equals(jsonResult.getString("side"), cardType)){
			result.setCode(CommonConstants.REQ_RESULT_FAIL);
        	result.setMessage("图片未识别，请更换清晰图片");
        	
        	return result;
		}
		
		//身份证照片的合法性检查结果
		JSONObject legality = jsonResult.getJSONObject("legality");
		if(legality != null && legality.getDouble("ID Photo") < LEGALITY_PROPORTION){
			result.setCode(CommonConstants.REQ_RESULT_FAIL);
        	result.setMessage("图片未识别，请更换清晰图片");
        	
        	return result;
		}
		
		//正面图片时校验身份证信息与实名认证信息是否一致
		if(IDCARD_FRONT.equals(jsonResult.getString("side"))){
			if(!StringUtils.equals(member.getIdcard(), jsonResult.getString("id_card_number"))||
					!StringUtils.equals(member.getRealName(), jsonResult.getString("name"))){
				result.setCode(CommonConstants.REQ_RESULT_FAIL);
	        	result.setMessage("身份证信息与实名认真信息不一致");
	        	
	        	return result;
			}
		}
		
		result.setCode(CommonConstants.REQ_RESULT_SUCC);
    	result.setMessage("身份证校验成功");
    	
    	return result;
	}
	
	public static ResultDto getFaceApiVerify(Member member, FileContants fileContants, byte[] VerifyFile){

		
		ResultDto result = new ResultDto();

		result.setCode(CommonConstants.REQ_RESULT_FAIL);

		//创建HttpClient对象
		CloseableHttpClient closeHttpClient = HttpClients.createDefault();
		CloseableHttpResponse httpResponse = null;
		//发送Post请求
		HttpPost httpPost = new HttpPost(fileContants.getFaceApiVerifyUrl());

		//设置Post参数
		MultipartEntity reqEntity = new MultipartEntity();

		try {
			reqEntity.addPart("api_key", new StringBody(fileContants.getFaceApiKey()));
			reqEntity.addPart("api_secret", new StringBody(fileContants.getFaceApiSecret()));
			//comparison_type   1：有源对比
			reqEntity.addPart("comparison_type", new StringBody("1"));
			reqEntity.addPart("idcard_name", new StringBody(member.getRealName(), StandardCharsets.UTF_8));
			reqEntity.addPart("idcard_number", new StringBody(member.getIdcard()));
			//face_image_type   raw_image：使用上传的图片验证
			reqEntity.addPart("face_image_type", new StringBody("raw_image"));
			
			reqEntity.addPart("image", new ByteArrayBody(VerifyFile, ""));
		} catch (UnsupportedEncodingException e) {
			LOGGER.error("人脸相识度识别返回值解析" + e.getMessage(), e);
		}
		

		//转换参数并设置编码格式
		httpPost.setEntity(reqEntity);
		//执行Post请求 得到Response对象
		try {
			httpResponse = closeHttpClient.execute(httpPost);
		} catch (ClientProtocolException e1) {
			
			e1.printStackTrace();
		} catch (IOException e1) {
			
			e1.printStackTrace();
		}
		
		result = checkHttpCode(httpResponse);
		
		if(CommonConstants.REQ_RESULT_FAIL.equals(result.getCode())){
			return result;
		}
		
		//把返回结果封装成json对象
        JSONObject jsonResult = null;
        if(httpResponse.getEntity() != null){
        	try {
				jsonResult = JSONObject.fromObject(EntityUtils.toString(httpResponse.getEntity(), "UTF-8"));
			} catch (ParseException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
        }
        if(httpResponse.getEntity() == null || jsonResult == null){
        	result.setCode(CommonConstants.REQ_RESULT_FAIL);
        	result.setMessage("请求失败，请重试");
        	
        	return result;
        }
        closeIO(httpResponse, closeHttpClient);
        JSONObject faceResult = (JSONObject) jsonResult.get("result_faceid");
        //相似度
		String confidence = faceResult.get("confidence").toString();
		
		faceResult = (JSONObject) jsonResult.get("id_exceptions");
		//相似度
		int id_attacked = faceResult.getInt("id_attacked");
			
		//大于60 验证成功
		if(new BigDecimal(confidence).compareTo(new BigDecimal(60)) !=  -1){
			result.setCode(CommonConstants.REQ_RESULT_SUCC);
			result.setData(id_attacked);
		}else {
			result.setCode(CommonConstants.REQ_RESULT_FAIL);
			result.setMessage("身份验证失败");
			result.setData(confidence);
		}
		
		return result;
	
	
		
	}
	
	private static ResultDto checkHttpCode(CloseableHttpResponse httpResponse) {
		ResultDto result = new ResultDto();
		result.setCode(CommonConstants.REQ_RESULT_FAIL);
		int responseCode = httpResponse.getStatusLine().getStatusCode();
		if(CODE_400 == responseCode){
			result.setMessage("图像质量不佳,请重试");
		}
		
		if(CODE_403 == responseCode){
			result.setMessage("系统繁忙，请稍后再试");
		}
		
		if(CODE_413 == responseCode){
			result.setMessage("图片文件过大");
		}
		
		if(CODE_404 == responseCode){
			result.setMessage("接口已失效");
		}
		
		if(CODE_500 == responseCode){
			result.setMessage("服务器内部错误，请联系客服人员");
		}
		
		if(CODE_200 == responseCode){
			result.setCode(CommonConstants.REQ_RESULT_SUCC);
		}
		
		return result;
	}
	
	private static void closeIO(CloseableHttpResponse httpResponse, CloseableHttpClient closeHttpClient){

		if(httpResponse != null){
			try {
				httpResponse.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		if(closeHttpClient != null){
			try {
				closeHttpClient.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	
	}
	/*public static void main(String[] args) throws IOException, IOException {
		InputStream inputStream = new URL("http://pic2.miercn.com/miercn/uploads/allimg/170407/151_170407084653_1.jpg")
				.openStream();
		FileContants fileContants = new FileContants();
		fileContants.setFaceApiKey("3jEekbp6xPdlJqEYuitfHE0AAvocW0Df");
		fileContants.setFaceApiSecret("M5dyLEr-9JubWwcrEpKcRlSu_a129Uhc");
		fileContants.setFaceApiOcridcardUrl("https://api.faceid.com/faceid/v1/ocridcard");
		byte frontCardData[] = StreamUtils.copyToByteArray(inputStream);
		
		Member member = new Member();
		member.setRealName("王清雷");
		member.setIdcard("140223198905100536");
		ResultDto result = ocridcard(member, fileContants, frontCardData, "1");
		System.out.println(result.getCode() + "----------" + result.getMessage());
	}*/

	/**
	 * 校验图片是否为身份证图片
	 * @param fileContants 文件常量文件
	 * @param cardFile 身份证图片
	 * @param cardType 图片类型 1正面 2背面
	 * @return 背面返回成功或者失败  正面成功时返回身份证号和姓名
	 */
	public static ResultDto checkBorrowIdcard(FileContants fileContants, byte[] cardFile, String cardType) {
		cardType = BorrowImgConstants.IMG_TYPE_1.equals(cardType) ? IDCARD_FRONT : IDCARD_BACK;
		ResultDto result = new ResultDto();
		result.setCode(CommonConstants.REQ_RESULT_FAIL);
		//创建HttpClient对象
		CloseableHttpClient closeHttpClient = HttpClients.createDefault();
		CloseableHttpResponse httpResponse = null;
		//发送Post请求
		HttpPost httpPost = new HttpPost(fileContants.getFaceApiOcridcardUrl());

		//设置Post参数
		MultipartEntity reqEntity = new MultipartEntity();

		try {
			reqEntity.addPart("api_key", new StringBody(fileContants.getFaceApiKey()));
			reqEntity.addPart("api_secret", new StringBody(fileContants.getFaceApiSecret()));
			//返回身份证照片合法性检查结果，值只取“0”或“1”。“1”：返回； “0”：不返回。默认“0”
			reqEntity.addPart("legality",new StringBody("1"));
		} catch (UnsupportedEncodingException e1) {
			LOGGER.error("************************身份证证件识别参数错误*******************************");
			e1.printStackTrace();
		}
		
		reqEntity.addPart("image", new ByteArrayBody(cardFile, ""));
		//转换参数并设置编码格式
		httpPost.setEntity(reqEntity);
		//执行Post请求 得到Response对象
		try {
			httpResponse = closeHttpClient.execute(httpPost);
		} catch (ClientProtocolException e) {
			LOGGER.error("身份证证件识别请求错误" + e.getMessage(), e);
		} catch (IOException e) {
			LOGGER.error("身份证证件识别请求错误" + e.getMessage(), e);
		}finally {
			closeIO(httpResponse, closeHttpClient);
		}
		
		result = checkHttpCode(httpResponse);
		
		if(CommonConstants.REQ_RESULT_FAIL.equals(result.getCode())){
			return result;
		}
		
		//把返回结果封装成json对象
        JSONObject jsonResult = null;
        if(httpResponse.getEntity() != null){
        	try {
				jsonResult = JSONObject.fromObject(EntityUtils.toString(httpResponse.getEntity(), "UTF-8"));
			} catch (ParseException e) {
				LOGGER.error("身份证证件识别返回值解析" + e.getMessage(), e);
			} catch (IOException e) {
				LOGGER.error("身份证证件识别返回值解析" + e.getMessage(), e);
			}
        }
        
        if(httpResponse.getEntity() == null || jsonResult == null){
        	result.setCode(CommonConstants.REQ_RESULT_FAIL);
        	result.setMessage("请求失败，请重试");
        	
        	return result;
        }
        //获取图片识别的正反面是否与传入的一致
		if(!StringUtils.equals(jsonResult.getString("side"), cardType)){
			result.setCode(CommonConstants.REQ_RESULT_FAIL);
        	result.setMessage("图片未识别，请更换清晰图片");
        	
        	return result;
		}
		
		//身份证照片的合法性检查结果
		JSONObject legality = jsonResult.getJSONObject("legality");
		if(legality != null && legality.getDouble("ID Photo") < LEGALITY_PROPORTION){
			result.setCode(CommonConstants.REQ_RESULT_FAIL);
        	result.setMessage("图片未识别，请更换清晰图片");
        	
        	return result;
		}
		
    	//正面图片时获取身份证信息
		if(IDCARD_FRONT.equals(jsonResult.getString("side"))){
			
			String name = jsonResult.getString("name");
			String idCardNumber = jsonResult.getString("id_card_number");
			if(!IdCardUtils.checkIdCard(idCardNumber)){
	    		result.setMessage("身份证号读取失败");
	    		
	    		return result;
	    	}
			JSONObject json = new JSONObject();
			json.put("name", name);
			json.put("idCardNumber", idCardNumber);
			json.put("address", jsonResult.getString("address"));
			result.setData(json);
		}
    	result.setCode(CommonConstants.REQ_RESULT_SUCC);
    	result.setMessage("身份证校验成功");
    	
    	return result;
	
	}
	
}
